/*
 *	Copyright (C) 2003-2006 Gabest
 *	http://www.gabest.org
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#pragma once

#include <atlcoll.h>
#include "VobSubImage.h"
#include "..\SubPic\ISubPic.h"

#define VOBSUBIDXVER 7

extern CString FindLangFromId(WORD id);

class CVobSubSettings
{
protected:
    HRESULT Render(SubPicDesc& spd, RECT& bbox);

public:
    CSize m_size;
    int m_x, m_y;
    CPoint m_org;
    int m_scale_x, m_scale_y;	// % (don't set it to unsigned because as a side effect it will mess up negative coordinates in GetDestrect())
    int m_alpha;				// %
    int m_fSmooth;				// 0: OFF, 1: ON, 2: OLD (means no filtering at all)
    int m_fadein, m_fadeout;	// ms
    bool m_fAlign;
    int m_alignhor, m_alignver; // 0: left/top, 1: center, 2: right/bottom
    unsigned int m_toff;				// ms
    bool m_fOnlyShowForcedSubs;
    bool m_fCustomPal;
    int m_tridx;
    RGBQUAD m_orgpal[16], m_cuspal[4];

    CVobSubImage m_img;

    CVobSubSettings()
    {
        InitSettings();
    }
    void InitSettings();

    bool GetCustomPal(RGBQUAD* cuspal, int& tridx);
    void SetCustomPal(RGBQUAD* cuspal, int tridx);

    void GetDestrect(CRect& r); // destrect of m_img, considering the current alignment mode
    void GetDestrect(CRect& r, int w, int h); // this will scale it to the frame size of (w, h)

    void SetAlignment(bool fAlign, int x, int y, int hor, int ver);
};

[uuid("998D4C9A-460F-4de6-BDCD-35AB24F94ADF")]
class CVobSubFile : public CVobSubSettings, public ISubStream, public ISubPicProviderImpl
{
protected:
    CString m_title;

    void TrimExtension(CString& fn);
    bool ReadIdx(CString fn, int& ver), ReadSub(CString fn), ReadRar(CString fn), ReadIfo(CString fn);
    bool WriteIdx(CString fn), WriteSub(CString fn);

    CMemFile m_sub;

    BYTE* GetPacket(int idx, int& packetsize, int& datasize, int iLang = -1);
    bool GetFrame(int idx, int iLang = -1);
    bool GetFrameByTimeStamp(__int64 time);
    int GetFrameIdxByTimeStamp(__int64 time);

    bool SaveVobSub(CString fn);
    bool SaveWinSubMux(CString fn);
    bool SaveScenarist(CString fn);
    bool SaveMaestro(CString fn);

public:
    typedef struct
    {
        __int64 filepos;
        __int64 start, stop;
        bool fForced;
        char vobid, cellid;
        __int64 celltimestamp;
        bool fValid;
    } SubPos;

    typedef struct
    {
        int id;
        CString name, alt;
        CAtlArray<SubPos> subpos;
    } SubLang;

    int m_iLang;
    SubLang m_langs[32];

public:
    CVobSubFile(CCritSec* pLock);
    virtual ~CVobSubFile();

    bool Copy(CVobSubFile& vsf);

    typedef enum {None, VobSub, WinSubMux, Scenarist, Maestro} SubFormat;

    bool Open(CString fn);
    bool Save(CString fn, SubFormat sf = VobSub);
    void Close();

    CString GetTitle()
    {
        return(m_title);
    }

    DECLARE_IUNKNOWN
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);

    // ISubPicProvider
    STDMETHODIMP_(POSITION) GetStartPosition(REFERENCE_TIME rt, double fps);
    STDMETHODIMP_(POSITION) GetNext(POSITION pos);
    STDMETHODIMP_(REFERENCE_TIME) GetStart(POSITION pos, double fps);
    STDMETHODIMP_(REFERENCE_TIME) GetStop(POSITION pos, double fps);
    STDMETHODIMP_(bool) IsAnimated(POSITION pos);
    STDMETHODIMP Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox);

    // IPersist
    STDMETHODIMP GetClassID(CLSID* pClassID);

    // ISubStream
    STDMETHODIMP_(int) GetStreamCount();
    STDMETHODIMP GetStreamInfo(int i, WCHAR** ppName, LCID* pLCID);
    STDMETHODIMP_(int) GetStream();
    STDMETHODIMP SetStream(int iStream);
    STDMETHODIMP Reload();
};

[uuid("D7FBFB45-2D13-494F-9B3D-FFC9557D5C45")]
class CVobSubStream : public CVobSubSettings, public ISubStream, public ISubPicProviderImpl
{
    CString m_name;

    CCritSec m_csSubPics;
    struct SubPic
    {
        REFERENCE_TIME tStart, tStop;
        CAtlArray<BYTE> pData;
    };
    CAutoPtrList<SubPic> m_subpics;

public:
    CVobSubStream(CCritSec* pLock);
    virtual ~CVobSubStream();

    void Open(CString name, BYTE* pData, int len);

    void Add(REFERENCE_TIME tStart, REFERENCE_TIME tStop, BYTE* pData, int len);
    void RemoveAll();

    DECLARE_IUNKNOWN
    STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void** ppv);

    // ISubPicProvider
    STDMETHODIMP_(POSITION) GetStartPosition(REFERENCE_TIME rt, double fps);
    STDMETHODIMP_(POSITION) GetNext(POSITION pos);
    STDMETHODIMP_(REFERENCE_TIME) GetStart(POSITION pos, double fps);
    STDMETHODIMP_(REFERENCE_TIME) GetStop(POSITION pos, double fps);
    STDMETHODIMP_(bool) IsAnimated(POSITION pos);
    STDMETHODIMP Render(SubPicDesc& spd, REFERENCE_TIME rt, double fps, RECT& bbox);

    // IPersist
    STDMETHODIMP GetClassID(CLSID* pClassID);

    // ISubStream
    STDMETHODIMP_(int) GetStreamCount();
    STDMETHODIMP GetStreamInfo(int i, WCHAR** ppName, LCID* pLCID);
    STDMETHODIMP_(int) GetStream();
    STDMETHODIMP SetStream(int iStream);
    STDMETHODIMP Reload()
    {
        return E_NOTIMPL;
    }
};
